接續昨天的實驗,我們用 unshare 指令做出了一個新的 PID namespace,其 id 為 4026532207:
$ sudo lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid     111     1 root /sbin/init
4026532207 pid       1 42009 root /bin/bash
讓我們在這個 4026532207 PID namespace 中執行一些時間比較長的指令,例如睡個幾千秒好了:
root@ip-xxx:/home/ubuntu# sleep 2000 &
[1] 13
root@ip-xxx:/home/ubuntu# sleep 2001 &
[2] 15
root@ip-xxx:/home/ubuntu# ps -ef 
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 15:35 pts/1    00:00:00 /bin/bash
root          13       1  0 15:54 pts/1    00:00:00 sleep 2000
root          15       1  0 16:05 pts/1    00:00:00 sleep 2001
root          16       1  0 16:05 pts/1    00:00:00 ps -ef
透過 ps 指令可以觀察到,在這個新的 PID namespace 中,可以看到在這個 namespace 啟動的所有 processes,且除了 /bin/bash (PID 為 1) 的其他 processes 的 PPID 皆為 1。
回到 Host 看一下:
ubuntu@ip-xxx:~$ sudo ps -e -o pidns,pid,ppid,args
     PIDNS     PID    PPID COMMAND
4026531836       1       0 /sbin/init
...略
4026531836   42007   41758 sudo unshare --pid --fork --mount-proc /bin/bash
4026531836   42008   42007 unshare --pid --fork --mount-proc /bin/bash
4026532207   42009   42008 /bin/bash
...略
4026532207   42050   42009 sleep 2000
4026532207   42088   42009 sleep 2001
4026531836   42090   41674 sudo ps -e -o pidns,pid,ppid,args
4026531836   42091   42090 ps -e -o pidns,pid,ppid,args
在 Host 是可以看到在新的這個 PID namespace 4026532207 中啟動的 3 個 processes: /bin/bash,  sleep 2000 與 sleep 2001,在 Host 裡 /bin/bash 的 PID 是 42009,sleep 2000 跟 sleep 2001 的 PPID 也是 42009。
如果我們在這個新建立的 PID namespace 4026532207 中又再執行一次 unshare 會發生什麼事呢?
root@ip-xxx:/home/ubuntu# unshare --pid --fork --mount-proc /bin/bash
root@ip-xxx:/home/ubuntu#
看起來好像什麼事都沒發生?用 lsns 看看:
root@ip-xxx:/home/ubuntu# lsns -t pid
        NS TYPE NPROCS PID USER COMMAND
4026532209 pid       2   1 root /bin/bash
可以看到,現在的 PID namespace 已經變成 4026532209 了,一樣啟動幾個時間比較長的 process 看看:
root@ip-xxx:/home/ubuntu# sleep 3000 &
[1] 9
root@ip-xxx:/home/ubuntu# sleep 3001 &
[2] 10
root@ip-xxx:/home/ubuntu# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 16:25 pts/1    00:00:00 /bin/bash
root           9       1  0 16:28 pts/1    00:00:00 sleep 3000
root          10       1  0 16:28 pts/1    00:00:00 sleep 3001
root          11       1  0 16:28 pts/1    00:00:00 ps -ef
回到 Host 看看:
ubuntu@ip-xxx:~$ sudo lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid     111     1 root /sbin/init
4026532207 pid       4 42009 root /bin/bash
4026532209 pid       1 42196 root /bin/bash
ubuntu@ip-xxx:~$ sudo ps -e -o pidns,pid,ppid,args | grep 4026532209
4026532209   42196   42195 /bin/bash
4026532209   42208   42196 sleep 3000
4026532209   42209   42196 sleep 3001
4026531836   42216   41674 grep --color=auto 4026532209
果然成功地多了一個新的 PID namespace 了,而且也可以看到 sleep 3000 跟 sleep 3001 這兩個 processes。
如果我想觀察看看在 4026532207 中能不能觀察到 4026532209 中的 processes,那就要先回到 4026532207 這個 namespace 中,如果用 exit 指令離開的話,這會終止 /bin/bash 這個 PID 為 1 的 process,這個時候 PID namespace 4026532209 也就跟著不見了(這個之後應該會討論到),因為我目前也不知道其他方式,所以還是先用 exit 離開,並且用背景的方式重新做一個 namespace 出來:
root@ip-xxx:/home/ubuntu# unshare --pid --fork --mount-proc sleep 5000 &
[1] 23
root@ip-xxx:/home/ubuntu# lsns -t pid
        NS TYPE NPROCS PID USER COMMAND
4026532207 pid       3   1 root /bin/bash
4026532209 pid       1  24 root sleep 5000
root@ip-xxx:/home/ubuntu# ps -e -o pidns,pid,ppid,args
     PIDNS     PID    PPID COMMAND
4026532207       1       0 /bin/bash
4026532207      23       1 unshare --pid --fork --mount-proc sleep 5000
4026532209      24      23 sleep 5000
4026532207      26       1 ps -e -o pidns,pid,ppid,args
這邊可以看到,一樣是在 4026532207 PID namespace 中建立了一個新的 PID namespace 4026532209,而在 4026532207 這裡是可以看到 4026532209 裡正在跑的 sleep 5000。
回到 Host 看一下:
ubuntu@ip-xxx:~$ sudo lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid     116     1 root /sbin/init
4026532207 pid       2 42400 root /bin/bash
4026532209 pid       1 42438 root sleep 5000
到這邊,我們可以先整理幾個觀察與網路上讀到的資料:
讓我們從 root PID namespace 再去建立一個新的 PID namespace:
ubuntu@ip-xxx:~$ sudo unshare --pid --fork --mount-proc /bin/bash
root@ip-xxx:/home/ubuntu# sleep 4000 &
[1] 8
root@ip-xxx:/home/ubuntu# sleep 4001 &
[2] 9
root@ip-xxx:/home/ubuntu# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 16:44 pts/2    00:00:00 /bin/bash
root           8       1  0 16:45 pts/2    00:00:00 sleep 4000
root           9       1  0 16:45 pts/2    00:00:00 sleep 4001
root          10       1  0 16:45 pts/2    00:00:00 ps -ef
root@ip-xxx:/home/ubuntu# lsns -t pid
        NS TYPE NPROCS PID USER COMMAND
4026532211 pid       4   1 root /bin/bash
在這個新的 PID namespace 4026532211 中是看不到其他 PID namespace 的 processes 的。
回到第一個被建立出來的 PID namespace 4026532207 中:
(實驗做太久,剛剛的 sleep 2000 已經睡醒了,重新跑一下,所以會排在後面)
root@ip-xxx:# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 16:56 pts/1    00:00:00 /bin/bash
root          23       1  0 17:03 pts/1    00:00:00 unshare --pid --fork --mount-proc sleep 5000
root          24      23  0 17:03 pts/1    00:00:00 sleep 5000
root          29       1  0 17:07 pts/1    00:00:00 sleep 2000
root          30       1  0 17:07 pts/1    00:00:00 sleep 2001
root          32       1  0 17:07 pts/1    00:00:00 ps -ef
這裡也一樣看不到 4026532211 中的 processes(但可以看到自已小孩 4026532209 裡的 process sleep 5000 喔)。
回到 Host:
ubuntu@ip-xxx:~$ sudo lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid     116     1 root /sbin/init
4026532207 pid       4 42400 root /bin/bash
4026532209 pid       1 42438 root sleep 5000
4026532211 pid       3 42447 root /bin/bash
ubuntu@ip-xxx:~$ sudo ps -e -o pidns,pid,ppid,args | grep 4026532209
4026532209   42438   42437 sleep 5000
4026531836   42472   41674 grep --color=auto 4026532209
ubuntu@ip-xxx:~$ sudo ps -e -o pidns,pid,ppid,args | grep 4026532211
4026532211   42447   42446 /bin/bash
4026532211   42455   42447 sleep 4000
4026532211   42456   42447 sleep 4001
4026531836   42475   41674 grep --color=auto 4026532211
Host 中可以看到新建立出來的 3 個 PID namespaces,也可以看到 4026532211 中的 processes。

用圖片示意一下 PID namespace 的父子關係,到這裡也可以發現,上對下是一覽無遺的,但下無法看到上的,平輩之間的也看不到。
我們利用 unshare 這個指令手動作出了不同的 PID namespace,也在其中執行了一些 processes,好用來觀察這些 processes 在不同的 namespace 中的「可見」程度,之後將會試著用別的方式再驗證一次,也會討論這些實驗跟 container 之間的關聯,是不是很好玩也很期待呢?